from fastapi import Depends

from app.core.BaseResponse import success, fail
from app.model import mysql
from app.service.folder import new_folder, get_folders, create_folder_media_photo, get_folder, remove_folder_medias, \
    copy_medias2folder, move_medias2folder, delete_folders, get_folder_all_files, get_user_collect_folder, \
    create_collect_folder, get_user_root_folder_ids, get_user_folder_ids_by_search, get_root_folder_by_folder_id
from app.service.format_datetime import format_datetime_group
from app.service.jwt_service import get_current_user
from app.service.media import get_media, get_media_custom_tags, update_media_base_info, get_my_media
from app.service.recycle import remove_user_recycles, remove_user_all_recycle, restore_recycles, get_user_recycles, \
    get_user_recycle_count
from app.service.response import response_manage_media, response_folder
from app.service.search import search_my_media
from app.service.user import get_user_custom_tags
from app.settings.config import LIMIT
from app.validator.app import schemas


async def my_medias(
        page: int = 1,
        timeType: int = 0,
        time: int = 0,
        mediaType: int = 0,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    全部图片
    :return:
    """
    time_type_dict = {
        1: 'year',
        2: 'month',
        3: 'day',
    }
    limit = LIMIT
    offset = (page - 1) * limit

    time_type = time_type_dict.get(timeType, '')
    time_value = time

    params = {
        "user_id": current_user.id,
        "offset": offset,
        "limit": limit,
        "time_type": time_type,
        "time_value": time_value,
        "media_type": mediaType,
    }

    items = []
    if time_type and not time_value:
        # --- 返回时间组结构数据 ---
        is_agg, total, infos = await search_my_media(params)
        for info in infos:
            if info.get('type') == 6:
                items.append(info)
            elif info.get('type') == 7:
                my_media = await get_my_media(info.get('user_id', 0), info.get('media_id', 0))
                if not my_media:
                    continue
                item = await response_manage_media(current_user.id, my_media.media_id)
                item['type'] = info.get('type')
                items.append(item)
    else:
        # --- 返回瀑布流结构数据 ---
        # 从第二页开始，列表获取前一页的最后一条，用于时间比较
        if page > 1:
            offset -= 1
            limit += 1
            params['offset'] = offset
            params['limit'] = limit
        is_agg, total, infos = await search_my_media(params)
        prev_time_group = ''
        for i, info in enumerate(infos):
            my_media = await get_my_media(info.get('user_id', 0), info.get('media_id', 0))
            if not my_media:
                continue
            # 获取时间归类
            time_group = format_datetime_group(my_media.created_time)
            if (prev_time_group or page == 1) and prev_time_group != time_group:
                items.append({
                    'type': 6,
                    'desc': time_group,
                })
            prev_time_group = f'{time_group}'
            if page > 1 and i == 0:
                continue

            item = await response_manage_media(current_user.id, my_media.media_id)
            items.append(item)

    data = {
        "total": total,
        "list": items
    }
    return success(data)


async def my_folders(
        page: int = 1,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    我的文件夹
    :return:
    """
    limit = LIMIT
    offset = (page - 1) * limit
    folder_ids = await get_user_root_folder_ids(current_user.id, offset=offset, limit=limit)
    items = []
    for folder_id in folder_ids:
        folder_info = await response_folder(current_user.id, folder_id)
        if folder_info:
            items.append(folder_info)
    return success(items)


async def create_folder(
        folder: schemas.Folder,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    新建文件夹
    :return:
    """
    name = folder.name
    description = folder.description
    parent_folder_id = folder.parentFolderId

    f = await new_folder(
        current_user.id,
        name,
        description=description,
        parent_folder_id=parent_folder_id,
        folder_types=2,
        filter_condition=''
    )
    return success({'id': f.id})


async def add_medias2folder(
        id: int,
        medias: schemas.Medias,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    添加N个媒体（图、图文...）到文件夹
    :return:
    """
    media_ids = medias.ids or []
    folder_id = id
    await copy_medias2folder(current_user.id, folder_id, media_ids)
    return success({})


async def delete_medias(
        medias: schemas.Medias,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    删除N个媒体（图、图文...）
    :return:
    """
    folder_id = medias.folderId
    media_ids = medias.ids or []
    if folder_id:
        folder = await get_folder(folder_id)
        if not folder:
            return fail(-1, '文件夹不存在，无法删除')
        if folder.user_id != current_user.id:
            return fail(-1, '无权限删除')
    await remove_folder_medias(current_user.id, folder_id, media_ids)
    return success({})


async def get_media_edit(
        id: int,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    获取编辑单图、多图、图文信息
    :return:
    """
    media = await get_media(id)
    if not media:
        return fail(-1, '信息不存在')
    if media.user_id != current_user.id:
        return fail(-1, '无权限查看')

    title = ''
    if media.object_type == mysql.Media.Type.photo:
        title = (media.data.text if media.data else '') or ''
    elif media.object_type == mysql.Media.Type.case:
        title = (media.data.title if media.data else '') or ''
    elif media.object_type == mysql.Media.Type.video:
        title = (media.data.text if media.data else '') or ''

    # -- 格式化标签列表 --
    user_custom_tags = await get_user_custom_tags(current_user.id)
    media_custom_tags = await get_media_custom_tags(current_user.id, media.id)
    media_custom_tags_set = set(media_custom_tags)

    # 排序
    arr = set(user_custom_tags) - set(media_custom_tags)
    arr = list(arr)
    arr.sort()
    media_custom_tags.extend(arr)
    user_custom_tags.sort(key=media_custom_tags.index)

    tags = []
    for tag in user_custom_tags:
        tags.append({
            'name': tag,
            'selected': tag in media_custom_tags_set,
        })

    data = {
        'id': media.id,
        'title': title,
        'canEditTitle': media.user_id == current_user.id,
        'tags': tags
    }
    return success(data)


async def update_media_edit(
        id: int,
        media_edit: schemas.MediaEdit,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    编辑单图、多图、图文信息
    :return:
    """
    media = await get_media(id)
    if not media:
        return fail(-1, '信息不存在')
    title = media_edit.title
    custom_tags = media_edit.customTags or []

    await update_media_base_info(current_user.id, media.id, title, custom_tags)
    return success({})


async def folders(
        current_user: schemas.User = Depends(get_current_user),
):
    """
    文件夹列表
    :return:
    """
    nest_items = await get_folders(current_user.id)
    return success(nest_items)


async def folder_detail(
        id: int,
        page: int = 1,
        mediaType: int = 0,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    文件夹详情
    :return:
    """
    limit = LIMIT
    offset = (page - 1) * limit
    # 从第二页开始，列表获取前一页的最后一条，用于时间比较
    if page > 1:
        offset -= 1
        limit += 1
    # 获取收藏夹编号
    folder_id = id
    folder = await get_folder(folder_id)
    if not folder:
        return fail(-1, '文件夹已被删除')
    folder_files = await get_folder_all_files(folder_id, offset=offset, limit=limit)
    items = []
    item_number = folder.sum_media_number
    prev_time_group = ''
    for i, folder_file in enumerate(folder_files):
        # 获取时间归类
        time_group = format_datetime_group(folder_file.created_time)
        if (prev_time_group or page == 1) and prev_time_group != time_group:
            items.append({
                'type': 6,
                'desc': time_group,
            })
        prev_time_group = f'{time_group}'
        if page > 1 and i == 0:
            continue

        item = await response_manage_media(current_user.id, folder_file.media_id)
        item['folderId'] = folder_file.folder_id
        items.append(item)

    # 获取一级文件夹名称
    root_folder = await get_root_folder_by_folder_id(folder.id, folder=folder)
    top_name = root_folder.name if root_folder else ''
    data = {
        'id': folder_id,
        'name': folder.name or '',
        'type': 2,
        'desc': folder.description or '',
        'photoNumber': item_number,
        'photos': items,
        'topName': top_name,
    }
    return success(data)


async def folder_search(
        id: int = 0,
        page: int = 1,
        keyword: str = '',
        mediaType: int = 0,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    文件夹内搜索
    :return:
    """
    folder = await get_folder(id)
    if not folder:
        return fail(-1, '文件夹不存在')
    limit = LIMIT
    offset = (page - 1) * limit

    folder_ids = [id]

    if page > 1:
        offset -= 1
        limit += 1

    params = {
        "user_id": current_user.id,
        "offset": offset,
        "limit": limit,
        "media_type": mediaType,
        "keyword": keyword,
        "folder_ids": folder_ids,
    }
    items = []
    is_agg, total, infos = await search_my_media(params)
    prev_time_group = ''
    for i, info in enumerate(infos):
        my_media = await get_my_media(info.get('user_id', 0), info.get('media_id', 0))
        if not my_media:
            continue
        # 获取时间归类
        time_group = format_datetime_group(my_media.created_time)
        if (prev_time_group or page == 1) and prev_time_group != time_group:
            items.append({
                'type': 6,
                'desc': time_group,
            })
        prev_time_group = f'{time_group}'
        if page > 1 and i == 0:
            continue

        item = await response_manage_media(current_user.id, my_media.media_id)
        items.append(item)

    return success(items)


async def create_media(
        create_media: schemas.CreateMedia,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    新增媒体（图片）
    :return:
    """
    kind = create_media.kind
    medias = create_media.medias
    folder_id = create_media.folderId
    if kind == 'photo':
        for exif in medias:
            await create_folder_media_photo(current_user.id, exif.dict(), folder_id)
    return success({})


async def get_folder_edit(
        id: int,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    获取编辑文件夹信息
    :return:
    """
    folder = await get_folder(id)
    if not folder:
        return fail(-1, '文件夹不存在')
    if folder.user_id != current_user.id:
        return fail(-1, '无权限查看')
    data = {
        'id': folder.id,
        'name': folder.name or '',
        'desc': folder.description or '',
    }
    return success(data)


async def update_folder_edit(
        id: int,
        into_folder: schemas.Folder,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    编辑文件夹
    :return:
    """
    folder = await get_folder(id)
    if not folder:
        return fail(-1, '文件夹不存在')
    if folder.user_id != current_user.id:
        return fail(-1, '无权限编辑')

    name = into_folder.name
    description = into_folder.description
    folder.name = name[:40]
    folder.description = description[:255]
    await folder.save()
    return success({})


async def my_collects(
        page: int = 1,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    我的收藏列表
    :return:
    """
    limit = LIMIT
    offset = (page - 1) * limit
    # 从第二页开始，列表获取前一页的最后一条，用于时间比较
    if page > 1:
        offset -= 1
        limit += 1
    # 获取收藏夹编号
    folder = await get_user_collect_folder(current_user.id)
    if not folder:
        folder = await create_collect_folder(current_user.id)
    folder_id = folder.id
    folder_files = await get_folder_all_files(folder_id, offset=offset, limit=limit)
    items = []
    item_number = folder.sum_media_number
    prev_time_group = ''
    for i, folder_file in enumerate(folder_files):
        # 获取时间归类
        time_group = format_datetime_group(folder_file.created_time)
        if (prev_time_group or page == 1) and prev_time_group != time_group:
            items.append({
                'type': 6,
                'desc': time_group,
            })
        prev_time_group = f'{time_group}'
        if page > 1 and i == 0:
            continue

        item = await response_manage_media(current_user.id, folder_file.media_id)
        if item:
            item['folderId'] = folder_file.folder_id
            items.append(item)
    data = {
        'id': folder_id,
        'name': '我的收藏',
        'type': 2,
        'desc': '这里是您收藏的全部图片',
        'photoNumber': item_number,
        'photos': items,
    }
    return success(data)


async def my_recycle(
        page: int = 1,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    回收站
    :return:
    """
    limit = LIMIT
    offset = (page - 1) * limit
    # 从第二页开始，列表获取前一页的最后一条，用于时间比较
    if page > 1:
        offset -= 1
        limit += 1
    recycles = await get_user_recycles(current_user.id, offset=offset, limit=limit)
    items = []
    prev_time_group = ''
    for i, recycle in enumerate(recycles):
        # 获取时间归类
        time_group = format_datetime_group(recycle.deleted_time)
        if (prev_time_group or page == 1) and prev_time_group != time_group:
            items.append({
                'type': 6,
                'desc': time_group,
            })
        prev_time_group = f'{time_group}'
        if page > 1 and i == 0:
            continue

        item = await response_manage_media(current_user.id, recycle.media_id)
        if item:
            item['folderId'] = recycle.folder_id
            item['recycleId'] = recycle.id
            items.append(item)
    item_number = await get_user_recycle_count(current_user.id)
    data = {
        'id': -1,
        'name': '回收站',
        'type': 2,
        'desc': '这里是您删除的全部图片',
        'photoNumber': item_number,
        'photos': items,
    }
    return success(data)


async def delete_recycle_all(
        current_user: schemas.User = Depends(get_current_user),
):
    """
    清空回收站
    :return:
    """
    await remove_user_all_recycle(current_user.id)
    return success({})


async def delete_recycle(
        recycles: schemas.Recycles,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    删除回收站选中数据
    :return:
    """
    recycle_ids = recycles.ids or []
    await remove_user_recycles(recycle_ids)
    return success({})


async def restore_recycle(
        recycles: schemas.Recycles,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    恢复回收站选中数据
    :return:
    """
    recycle_ids = recycles.ids or []
    folder_id = recycles.folderId or 0
    success_ids, fail_ids = await restore_recycles(recycle_ids, folder_id=folder_id)
    return success({"successIds": success_ids, "failIds": fail_ids})


async def move_folder_media(
        move_medias: schemas.MoveMedias,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    移动选中文件夹文件到其他文件夹
    :return:
    """
    media_ids = move_medias.ids or []
    from_folder_id = move_medias.fromFolderId
    to_folder_id = move_medias.toFolderId
    from_folder = await get_folder(from_folder_id)
    if not from_folder:
        return fail(-1, '此文件夹不存在')
    if from_folder.user_id != current_user.id:
        return fail(-1, '没有权限编辑此文件夹')
    to_folder = await get_folder(to_folder_id)
    if not to_folder:
        return fail(-1, '目标文件夹不存在')
    if to_folder.user_id != current_user.id:
        return fail(-1, '没有权限编辑目标文件夹')
    await move_medias2folder(current_user.id, from_folder_id, to_folder_id, media_ids)

    is_delete = not to_folder.path.startswith(from_folder.path)  # 告诉前端要不要从页面上移除，True:目标文件夹不是源文件夹子集
    data = {
        "isDelete": is_delete
    }
    return success(data)


async def delete_folder(
        remove_folders: schemas.RemoveFolders,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    删除文件夹
    :return:
    """
    folder_ids = remove_folders.ids or []
    await delete_folders(current_user.id, folder_ids)
    return success({})


async def search_folders(
        page: int = 1,
        keyword: str = '',
        current_user: schemas.User = Depends(get_current_user),
):
    """
    全部图片搜索-文件夹
    :return:
    """
    limit = LIMIT
    offset = (page - 1) * limit
    items = []
    if keyword:
        folder_ids = await get_user_folder_ids_by_search(current_user.id, keyword, offset=offset, limit=limit)
        for folder_id in folder_ids:
            folder_info = await response_folder(current_user.id, folder_id)
            if folder_info:
                items.append(folder_info)
    return success(items)


async def search_medias(
        page: int = 1,
        keyword: str = '',
        mediaType: int = 0,
        current_user: schemas.User = Depends(get_current_user),
):
    """
    全部图片搜索-图片
    :return:
    """
    limit = LIMIT
    offset = (page - 1) * limit

    if page > 1:
        offset -= 1
        limit += 1

    params = {
        "user_id": current_user.id,
        "offset": offset,
        "limit": limit,
        "media_type": mediaType,
        "keyword": keyword,
    }
    items = []
    if keyword:
        is_agg, total, infos = await search_my_media(params)
        prev_time_group = ''
        for i, info in enumerate(infos):
            my_media = await get_my_media(info.get('user_id', 0), info.get('media_id', 0))
            if not my_media:
                continue
            # 获取时间归类
            time_group = format_datetime_group(my_media.created_time)
            if (prev_time_group or page == 1) and prev_time_group != time_group:
                items.append({
                    'type': 6,
                    'desc': time_group,
                })
            prev_time_group = f'{time_group}'
            if page > 1 and i == 0:
                continue

            item = await response_manage_media(current_user.id, my_media.media_id)
            items.append(item)

    return success(items)
